def exception_handler(exc, context):
    """
    Returns the response that should be used for any given exception.

    By default we handle the REST framework `APIException`, and also
    Django's built-in `Http404` and `PermissionDenied` exceptions.

    Any unhandled exceptions may return `None`, which will cause a 500 error
    to be raised.
    """
    if isinstance(exc, exceptions.Error):
        set_rollback()
        return Response(exc.err_data(), status=exc.status_code)

    if isinstance(exc, Http404):
        exc = exceptions.NotFound()
    elif isinstance(exc, PermissionDenied):
        exc = exceptions.AccessDenied(message=str(exc))
    elif isinstance(exc, AuthenticationFailed):
        exc = exceptions.AuthenticationFailed(message=str(exc))
    elif isinstance(exc, NotAuthenticated):
        exc = exceptions.NotAuthenticated(message=str(exc))
    elif isinstance(exc, APIException):
        if isinstance(exc.detail, (list, dict)):
            data = exc.detail
        else:
            data = {'detail': exc.detail}

        exc = exceptions.Error(message=str(data), status_code=exc.status_code, code=exc.default_code)
    else:
        exc = exceptions.convert_to_error(exc)

    set_rollback()
    logger.error(msg=str(exc))
    return Response(exc.err_data(), status=exc.status_code)